package check

import (
	"gitee.com/u-language/u-language/ucom/ast"
	"gitee.com/u-language/u-language/ucom/errcode"
)

// checkFor 对一个for语句进行语义检查
//   - ptr是被检查的for语句节点
//   - t是被检查节点所属的抽象语法树
//   - InAutoFree指示是否在自动释放块内
func checkFor(ptr *ast.ForNode, t *ast.Tree, InAutoFree bool) (errcode.ErrCode, errcode.Msg) {
	err := checkForInitStmt(ptr.InitStmt)
	if err != errcode.NoErr {
		return err, nil
	}
	err, msg := checkForBoolExpr(ptr.BoolExpr, ptr.Sbt, t, InAutoFree)
	if err != errcode.NoErr {
		return err, msg
	}
	return checkForEndStmt(ptr, t, InAutoFree)
}

// checkForInitStmt 检查for的初始化语句
func checkForInitStmt(ptr ast.Node) errcode.ErrCode {
	if ptr == nil { //检查是否是允许的为空
		return errcode.NoErr
	}
	if _, isvar := ptr.(*ast.VarNode); !isvar { //如果不是声明变量
		return errcode.ForInitNoDeclVarStmt
	}
	return errcode.NoErr
}

// checkForBoolExpr 检查for的布尔表达式
func checkForBoolExpr(ptr ast.Expr, sbt *ast.Sbt, t *ast.Tree, InAutoFree bool) (errcode.ErrCode, errcode.Msg) {
	if ptr == nil { //检查是否是允许的为空
		return errcode.NoErr, nil
	}
	return CheckBoolExprNode(ptr, sbt, t, InAutoFree)
}

// checkForEndStmt 检查for的结束语句
func checkForEndStmt(f *ast.ForNode, t *ast.Tree, InAutoFree bool) (errcode.ErrCode, errcode.Msg) {
	if f.EndStmt == nil { //检查是否是允许的为空
		return errcode.NoErr, nil
	}
	switch stmt := f.EndStmt.(type) {
	case *ast.ASSIGNNode:
		return CheckASSIGN(stmt, f.Sbt, t, InAutoFree)
	case *ast.SelfOpStmt:
		return checkSelfOpStmtCtx(stmt, f.Sbt, t, InAutoFree)
	}
	return errcode.ForEndStmt, nil
}
